package hbt;

import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;

import remoto.CoordinadorTO;
import dominio.Contrato;

public class HibernateDAO {
	protected static HibernateDAO instancia;
	protected SessionFactory sf;
	protected Session session;
	
	static {
		instancia = new HibernateDAO();
	}


	protected HibernateDAO(){
		sf = HibernateUtil.getSessionFactory();
	}

	public static HibernateDAO getInstancia() {
//		if (instancia == null){
//			instancia = new HibernateDAO();
//		}
		return instancia;
	}
	
	public SessionFactory getSf() {
		return sf;
	}
	public void setSf(SessionFactory sf) {
		this.sf = sf;
	}
	public Session getSession() {
		if (session == null || !session.isOpen()){
			session = sf.openSession();
		}
		return session;
	}
	public void closeSession(){
		if (session.isOpen()){
			session.close();
		}
	}

	public void persist(Object obj) {
		Session session = getSession();
		session.beginTransaction();
		session.persist(obj);
		session.getTransaction().commit();
	}

	@SuppressWarnings("rawtypes")
	public void persistList(List lista){
		Session session = getSession();
		session.beginTransaction();
		for(Object e : lista){
			session.merge(e);
		}
		session.flush();
		session.getTransaction().commit();
	}

	@SuppressWarnings("rawtypes")
	public Object get (Class c, Object o) {
		Session session = getSession();
		return session.get(c, (Serializable) o);
	}

	public List<?> getLista(String query) {
		Session session = getSession();
		List<?> lista = session.createQuery(query).list();
		return lista;
	}
	
	public List<?> parametros(String query, String prmName, String prm) {
		Session session = getSession();
		List<?> lista = session.createQuery(query).setParameter(prmName, prm).list();
		return lista;
	}
	
	public Object propiedades(String query, Object obj) {
		Session session = getSession();
		Object object = session.createQuery(query).setProperties(obj).uniqueResult();
		return object;
	}
	
	@SuppressWarnings("unchecked")
	public List<Object[]> tuplas(String query) {
		Session session = getSession();
		List<Object[]> lista = session.createQuery(query).list();
		return lista;
	}
	
	public Object totalizador(String query) {
		Session session = getSession();
		Object obj = session.createQuery(query).uniqueResult();
		return obj;
	}

	public void save(Object o) {
		Session session = this.getSession();
		session.beginTransaction();
		session.save(o);
		session.getTransaction().commit();
	}

	public void load(Object o, Serializable id) {
		Session session = this.getSession();
		session.beginTransaction();
		session.load(o, id);
		session.getTransaction().commit();
	}
	
	public Contrato convenioMayorMonto() {
		Session session = this.getSession();
		session.beginTransaction();
		String sentencia = "select con from Contrato con join con.integrante inte"
				+ " where (con.convenio.horas * con.convenio.valorHora) = "
				+ "    (select max(c.convenio.horas * c.convenio.valorHora) from Convenio c join c.integrante i"
				+ "    where i.class = Desarrollador)"
				+ " and inte.class = Desarrollador";
		Query q = session.createQuery(sentencia );
		return (Contrato) q.uniqueResult();
	}
	
	public List<Contrato> getContratosDeCoordinadoras() {
		Session session = this.getSession();
		session.beginTransaction();
		
		String[] pFun = {"Implementacion","Control"};
		String pSex = "feme";

		String query = 
		"select con from Contrato con join con.proyecto.funciones fun "
			+ "where fun.nombre in (:funcion) and con.integrante.sexo = :sexo "
			+ "and con.integrante.id in (select coo.id from Coordinador coo)";
		
		List<Contrato> contratos = session.createQuery(query)
			.setParameterList("funcion", pFun)
			.setParameter("sexo", pSex)
			.list();
		
		contratos= new LinkedList<Contrato>();
		Contrato c1 = new Contrato();
		c1.setId(1);
		Contrato c2 = new Contrato();
		c1.setId(2);
		
		contratos.add(c1 );
		contratos.add(c2);
			
		System.out.println("Nombre del Proyecto e integrantes femeninos de proyectos que contemplan implementacion y control ");
		return contratos;
	}

	public String convenioDeMayorMonto() {
		Session session = this.getSession();
		session.beginTransaction();

		Object res = session
				.createCriteria(
						"select c.proyecto.nombre c.integrante.nombre, max(c.convenio.valorHora) FROM Contrato c where c.integrante.id in (select d.id from Desarrollador d)")
				.addOrder(Order.desc("c.convenio.valorHora")).uniqueResult();
		Query q = session
				.createQuery("select p.nombre, i.nombre, max(c.convenio.valorHora) FROM Contrato c INNER JOIN Integrante i INNER JOIN Desarrollador d INNER JOIN Proyecto p");
		Object[] result = (Object[]) q.uniqueResult();

		StringBuilder sb = new StringBuilder();

		for (int i = 0; i < result.length; i++) {
			sb.append(result[i]);
		}

		return sb.toString();
	}

	public CoordinadorTO getCoordinadora() {
		Session session = this.getSession();
		session.beginTransaction();

		List<String> nombres = session
				.createQuery(
						"select c.integrante.nombre FROM Contrato c join  where c.proyecto in (select p from Proyecto p where p.funcion.nombre or c.proyecto.funcion.nombre='Control')")
				.list();

		nombres.get(0);
		// pasar al dto
		return null;
	}
	
}
